package com.hup.sidebar.view;

import android.annotation.SuppressLint;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Build;
import android.os.Build.VERSION_CODES;
import android.os.Bundle;
import android.provider.Settings;
import android.text.InputType;
import android.text.SpannableString;
import android.text.Spanned;
import android.text.TextUtils;
import android.text.style.AbsoluteSizeSpan;
import android.util.Log;
import android.view.Gravity;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.CompoundButton;
import android.widget.EditText;
import android.widget.SeekBar;
import android.widget.SeekBar.OnSeekBarChangeListener;
import android.widget.TableRow;
import android.widget.TextView;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.StringRes;
import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AlertDialog.Builder;
import androidx.appcompat.app.AppCompatActivity;

import com.hup.sidebar.R;
import com.hup.sidebar.SideBarApplication;
import com.hup.sidebar.androidService.AppService;
import com.hup.sidebar.constant.PieFunctionConstant;
import com.hup.sidebar.framework.SubThreadHandler;
import com.hup.sidebar.framework.util.BuildConfigUtil;
import com.hup.sidebar.framework.util.PermissionUtil;
import com.hup.sidebar.framework.util.ToastUtil;
import com.hup.sidebar.model.AppConfig;
import com.hup.sidebar.service.ActivationFloaterService;
import com.skydoves.colorpickerview.ColorPickerDialog;
import com.skydoves.colorpickerview.ColorPickerView;
import com.skydoves.colorpickerview.flag.BubbleFlag;
import com.skydoves.colorpickerview.listeners.ColorEnvelopeListener;

import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;

/**
 * @author hugan
 * @date 2022/6/3
 */
public class MainActivity extends AppCompatActivity {
    private static final String TAG = MainActivity.class.getSimpleName();
    private static final int REQUEST_OVERLAY = 1000;
    private static final int REQUEST_CONFIG = 1001;

    private MainForm form;

    private AppConfig appConfig;
    private SharedPreferences configSp;
    private int seekbarSmallFont;
    private boolean hadInit;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        if (!isTaskRoot() || (getIntent().getFlags() & Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT) != 0) {
            Log.i(TAG, "onCreate: 过滤重复启动");
            finish();
            return;
        }
        Log.i(TAG, "onCreate: ");
        seekbarSmallFont = getResources().getDimensionPixelSize(R.dimen.seekbar_small_font);
        appConfig = SideBarApplication.getBean(AppConfig.class);
        configSp = appConfig.getSp(this);
        //Log.i(TAG, "onCreate: appConfig={}" + appConfig);

        initView();
        initListener();

        SideBarApplication.putBean(this);
        hadInit = true;

        //启动时开启服务
        if (appConfig.autoStart && !appConfig.floaterStarted) {
            tryStartService();
        }
    }

    private void initView() {
        setContentView(MainForm.RESOURCE_ID);
        form = new MainForm(this);
        form.cbStartService.setChecked(appConfig.floaterStarted);
        onAccessibilityStarted(appConfig.accessibilityStarted);
        setLineWrapText(form.cbShowNote, R.string.main_show_note);
        setLineWrapText(form.cbShowTempHide, R.string.main_show_temp_hide);
        setLineWrapText(form.cbUseTrampoline, R.string.main_trampoline_desc);
        form.cbShowNote.setChecked(appConfig.noteShow);
        form.cbShowTempHide.setChecked(appConfig.tempHideShow);
        form.cbUseTrampoline.setChecked(appConfig.useTrampoline);

        ActionBar actionBar = getSupportActionBar();
        if (actionBar != null) {
            actionBar.setIcon(R.mipmap.ic_launcher);
            actionBar.setDisplayShowHomeEnabled(true);
        }
    }

    private void initListener() {
        form.btnGotoAccessibility.setOnClickListener(v -> {
            Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
            startActivity(intent);
            //TestUtil.testUpdateCachedIcon(v);
        });
        form.cbStartService.setOnCheckedChangeListener((v, isChecked) -> {
            if (!v.isPressed()) return;//过滤setChecked事件
            Log.i(TAG, "cbStartService: " + isChecked);
            v.setEnabled(false);
            if (isChecked) {
                tryStartService();
            } else {
                AppService.switchService(false);
            }
            //v.setEnabled(true);//由AppService处理完才更新
        });
        initCheckbox(form.cbAutoStart, "autoStart");
        form.btnWhiteList.setOnClickListener(v -> {
            Intent intent = new Intent(this, WhiteListActivity.class);
            startActivity(intent);
        });

        //=== 激活器
        if (Build.VERSION.SDK_INT < VERSION_CODES.O) {
            ToastUtil.long_(getString(R.string.not_compat));
            Log.e(TAG, "initSeekbar: 未适配!");
        }
        initSeekbar(form.sbActiveWidth, "activeWidth");
        initSeekbar(form.sbActiveHeight, "activeHeight");
        initSeekbar(form.sbActiveYOffset, "activeYOffset");

        //=== 功能区:appConfig更新后都不用通知view
        form.btnPieFunction.setOnClickListener(v -> {
            v.setEnabled(false);
            Intent intent = new Intent(this, PieFunctionActivity.class);
            startActivity(intent);
            v.setEnabled(true);
        });
        initColorButton(form.btnPieColor, "pieColorStr");
        initColorButton(form.btnPieColorFont, "pieColorFontStr");
        initSeekbar(form.sbPieRadius, "pieRadius");
        initSeekbar(form.sbPieWidth, "pieWidth");
        initSeekbar(form.sbPieGap, "pieGap");
        initSeekbar(form.sbPieIconRatio, "pieIconRatio");
        initSeekbar(form.sbPieLongPressTime, "pieLongPressTime");
        initCheckbox(form.cbPieVibrate, "pieVibrate");
        initSeekbar(form.sbVibrateTime, "vibrateTime");
        //
        initCheckbox(form.cbPieShowIndicator, "pieShowIndicator");

        //=== 便签
        initCheckbox(form.cbShowNote, "noteShow");
        initSeekbar(form.sbNoteFontSize, "noteFontSize");
        initCheckbox(form.cbNoteDateShow, "noteDateShow");
        initNoteDateFormat();
        //===临时关闭
        initCheckbox(form.cbShowTempHide, "tempHideShow");
        //
        initCheckbox(form.cbUseTrampoline, "useTrampoline");
    }

    private void initColorButton(View button, String fieldName) {
        button.setOnClickListener(v -> {
            int color = ("pieColorStr".equals(fieldName)) ? appConfig.pieColor : appConfig.pieColorFont;
            ColorPickerDialog.Builder builder = new ColorPickerDialog.Builder(this)
                    .setTitle(((TextView) v).getText())
                    .setCancelable(false)
                    .setPositiveButton(getString(R.string.confirm), (ColorEnvelopeListener) (envelope, fromUser) -> {
                        Log.i(TAG, fieldName + "=" + envelope.getHexCode());
                        appConfig.set(fieldName, "#" + envelope.getHexCode(), configSp);
                        appConfig.applyPieColor();
                    })
                    .setNegativeButton(getString(R.string.cancel), (dialogInterface, i) -> dialogInterface.dismiss());
            ColorPickerView pickerView = builder.getColorPickerView();
            pickerView.setInitialColor(color);
            pickerView.setFlagView(new BubbleFlag(this));
            builder.show();
        });
        button.setOnLongClickListener(v -> {
            appConfig.reset(fieldName, configSp);
            appConfig.applyPieColor();
            ToastUtil.short_(getString(R.string.main_restore_def_value) + appConfig.get(fieldName));
            return true;
        });
    }


    /**
     * 设置监听和更新值
     */
    private void initSeekbar(SeekBar seekBar, String fieldName) {
        Object defValue = appConfig.getDefault(fieldName);
        //点击label
        TextView label = (TextView) ((TableRow) seekBar.getParent()).getChildAt(0);//找同一行的label
        if (seekBar == form.sbActiveWidth || seekBar == form.sbActiveHeight || seekBar == form.sbActiveYOffset) {
            label.setOnClickListener(v -> {
                SideBarApplication.executeIfExist(ActivationFloaterService.class, service -> service.setActivationVisible(true));
                ToastUtil.short_(getString(R.string.main_def_value) + defValue);
            });
        } else {
            label.setOnClickListener(v -> ToastUtil.short_(getString(R.string.main_def_value) + defValue));
        }
        //seekBar
        OnSeekBarChangeListener listener = new OnSeekBarChangeListener() {
            final String originalText = label.getText().toString();//原始字符串
            final int wrapIndex = originalText.indexOf('\n');

            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                //Log.i(TAG, "onProgressChanged: " + fieldName + "=" + progress);
                //格式化标签和取值,设置不同字体样式
                SpannableString spannable;
                if (progress == 0 && seekBar == form.sbVibrateTime) {
                    spannable = new SpannableString(new SpannableString(String.format(originalText, getString(R.string.main_pie_vibrate_default))));
                } else {
                    spannable = new SpannableString(new SpannableString(String.format(originalText, progress)));
                }
                spannable.setSpan(new AbsoluteSizeSpan(seekbarSmallFont), wrapIndex, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
                label.setText(spannable);
                appConfig.set(fieldName, progress);
                if (!hadInit) return;
                if (fieldName.startsWith("active")) {
                    SideBarApplication.executeIfExist(ActivationFloaterService.class, ActivationFloaterService::onActivationConfigUpdated);
                }
            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {
                //保存数据
                int progress = seekBar.getProgress();
                Log.i(TAG, "onStopTrackingTouch: " + fieldName + ", " + progress);
                appConfig.set(fieldName, progress, configSp);

                //通知更新pieView
                boolean updatePieView = fieldName.startsWith("pie") && !fieldName.equals("pieLongPressTime");
                if (fieldName.equals("noteFontSize")) updatePieView = true;
                if (updatePieView) {
                    PieFunctionConstant.updateCachedIcon(appConfig);
                    SideBarApplication.executeIfExist(ActivationFloaterService.class, ActivationFloaterService::onPieConfigUpdated);
                }
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {
            }
        };
        seekBar.setOnSeekBarChangeListener(listener);
        seekBar.setTag(listener);
        //长按label
        label.setOnLongClickListener(v -> {
            ToastUtil.short_(getString(R.string.main_restore_def_value) + defValue);
            seekBar.setProgress((Integer) defValue);
            listener.onStopTrackingTouch(seekBar);
            return true;
        });

        //先添加监听, 再更新值:触发更新label
        int value = appConfig.get(fieldName);
        seekBar.setProgress(value);
        int min = 0;
        if (Build.VERSION.SDK_INT >= VERSION_CODES.O) {
            min = seekBar.getMin();
        }
        //Log.i(TAG, "initSeekbar: " + saveKey + "=" + value);
        if (value == 0 || value == min) {
            //seekbar值没变,要主动触发事件
            listener.onProgressChanged(seekBar, value, false);
        }
    }

    /**
     * 更新值,设置监听
     */
    private void initCheckbox(CompoundButton checkbox, String fieldName) {
        boolean value = appConfig.get(fieldName);
        checkbox.setChecked(value);
        checkbox.setOnCheckedChangeListener((v, isChecked) -> {
            Log.i(TAG, "checkedChange: " + fieldName + ", " + isChecked);
            appConfig.set(fieldName, isChecked, configSp);
        });
    }

    private void initNoteDateFormat() {
        form.txtNoteDateFormat.setText(appConfig.noteDateFormat);
        form.txtNoteDateFormat.setOnClickListener(v -> {
            final EditText input = new EditText(this);
            input.setInputType(InputType.TYPE_CLASS_TEXT);
            input.setText(appConfig.noteDateFormat);
            input.setGravity(Gravity.CENTER_HORIZONTAL);

            AlertDialog dialog = new Builder(this)
                    .setTitle(R.string.main_note_date_tips)
                    .setView(input)
                    .setCancelable(false)
                    .setPositiveButton(R.string.confirm, null)
                    .setNegativeButton(R.string.cancel, null)
                    .create();
            dialog.show();
            dialog.getButton(AlertDialog.BUTTON_POSITIVE).setOnClickListener(view -> {
                String format = input.getText().toString().trim();
                Log.i(TAG, "txtNoteDateFormat: " + format);
                try {
                    if (TextUtils.isEmpty(format)) {
                        throw new IllegalArgumentException("empty");
                    }
                    SimpleDateFormat formatter = new SimpleDateFormat(format, Locale.getDefault());
                    String date = formatter.format(new Date());
                    ToastUtil.short_(date);

                    appConfig.noteDateFormat = format;
                    appConfig.noteDateFormatter = formatter;
                    form.txtNoteDateFormat.setText(appConfig.noteDateFormat);
                    appConfig.set("noteDateFormat", format, configSp);
                    dialog.dismiss();
                } catch (Exception e) {
                    Log.e(TAG, "txtNoteDateFormat: " + e.getMessage());
                    ToastUtil.short_(getString(R.string.main_note_date_error));
                }
            });
        });
    }

    private void updateConfig() {
        updateCheckbox(form.cbAutoStart, "autoStart");
        //
        updateSeekbar(form.sbActiveWidth, "activeWidth");
        updateSeekbar(form.sbActiveHeight, "activeHeight");
        updateSeekbar(form.sbActiveYOffset, "activeYOffset");
        //
        updateSeekbar(form.sbPieRadius, "pieRadius");
        updateSeekbar(form.sbPieWidth, "pieWidth");
        updateSeekbar(form.sbPieGap, "pieGap");
        updateSeekbar(form.sbPieIconRatio, "pieIconRatio");
        updateSeekbar(form.sbPieLongPressTime, "pieLongPressTime");
        updateCheckbox(form.cbPieVibrate, "pieVibrate");
        updateSeekbar(form.sbVibrateTime, "vibrateTime");
        updateCheckbox(form.cbPieShowIndicator, "pieShowIndicator");
        //=== 便签
        updateCheckbox(form.cbShowNote, "noteShow");
        updateSeekbar(form.sbNoteFontSize, "noteFontSize");
        updateCheckbox(form.cbNoteDateShow, "noteDateShow");
        form.txtNoteDateFormat.setText(appConfig.noteDateFormat);
        //===临时关闭
        updateCheckbox(form.cbShowTempHide, "tempHideShow");
        //
        updateCheckbox(form.cbUseTrampoline, "useTrampoline");
    }

    private void updateSeekbar(SeekBar seekBar, String fieldName) {
        int value = appConfig.get(fieldName);
        int oldValue = seekBar.getProgress();
        if (value == oldValue) {
            return;
        }
        seekBar.setProgress(value);//触发 onProgressChanged
        OnSeekBarChangeListener listener = (OnSeekBarChangeListener) seekBar.getTag();
        listener.onStopTrackingTouch(seekBar);
    }

    private void updateCheckbox(CompoundButton checkbox, String fieldName) {
        boolean value = appConfig.get(fieldName);
        checkbox.setChecked(value);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main_activity_menu, menu);
        return super.onCreateOptionsMenu(menu);
    }

    @SuppressLint("SetTextI18n")
    @Override
    public boolean onOptionsItemSelected(@NonNull MenuItem item) {
        if (item.getItemId() == R.id.menu_info) {
            Log.d(TAG, "onOptionsItemSelected: info");
            Builder builder = new Builder(this);
            builder.setView(R.layout.app_info_dialog);
            AlertDialog dialog = builder.create();
            dialog.show();//要show后才能findViewById
            //赋值
            TextView txtVersion = dialog.findViewById(R.id.txtVersion);
            assert txtVersion != null;
            TextView txtBuildTime = dialog.findViewById(R.id.txtBuildTime);
            assert txtBuildTime != null;
            if ("release".equalsIgnoreCase(BuildConfigUtil.getBuildType())) {
                txtVersion.setText(BuildConfigUtil.getVersion());
                txtBuildTime.setText(BuildConfigUtil.getPackageTime().substring(0, 8));
            } else {
                txtVersion.setText(BuildConfigUtil.getBuildType() + " " + BuildConfigUtil.getVersion());
                txtBuildTime.setText(BuildConfigUtil.getPackageTime());
            }
        } else if (item.getItemId() == R.id.menu_config_export) {
            Intent intent = new Intent(this, ConfigExportActivity.class);
            startActivityForResult(intent, REQUEST_CONFIG);
        }
        return true;
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        Log.i(TAG, "onActivityResult: " + requestCode + ", " + resultCode);
        if (REQUEST_OVERLAY == requestCode) {
            boolean hasOverlayPermission = PermissionUtil.hasOverlayPermission(this);
            Log.i(TAG, "onActivityResult: 悬浮窗权限.请求结果" + hasOverlayPermission);
            if (hasOverlayPermission) AppService.switchService(true);
        } else if (REQUEST_CONFIG == requestCode) {
            updateConfig();
        }
    }

    @Override
    public void onBackPressed() {
        finish();
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i(TAG, "onDestroy: " + hadInit);
        if (!hadInit) return;
        SideBarApplication.removeBean(getClass());
        SideBarApplication.executeIfExist(ActivationFloaterService.class, service -> service.setActivationVisible(false));

        //没启动服务的,就关闭app
        SideBarApplication.getBean(SubThreadHandler.class).postDelayed(() -> {
            boolean floaterStarted = appConfig.floaterStarted;
            boolean accessibilityStarted = appConfig.accessibilityStarted;
            Log.i(TAG, "onDestroy: floaterStarted, accessibilityStarted=" + floaterStarted + ", " + accessibilityStarted);
            if (!floaterStarted && !accessibilityStarted) System.exit(0);
        }, 200);
    }

    private void tryStartService() {
        if (PermissionUtil.hasOverlayPermission(this)) {
            AppService.switchService(true);
        } else {
            form.cbStartService.setChecked(false);
            form.cbStartService.setEnabled(true);
            ToastUtil.short_(getString(R.string.main_none_floater_auth));
            //申请权限
            PermissionUtil.acquireOverlayPermission(this, REQUEST_OVERLAY);
        }
    }

    public void onFloaterStarted(boolean b) {
        form.cbStartService.setChecked(b);
        form.cbStartService.setEnabled(true);
        if (b) {
            ToastUtil.short_(getString(R.string.service_started));
        }
    }

    public void onAccessibilityStarted(boolean b) {
        if (b) {
            form.btnGotoAccessibility.setText(R.string.main_accessibility_started);
        } else {
            setLineWrapText(form.btnGotoAccessibility, R.string.main_accessibility_stopped);
        }
    }

    private void setLineWrapText(TextView textView, @StringRes int resId) {
        String str = getString(resId);
        SpannableString spannable = new SpannableString(new SpannableString(str));
        int wrapIndex = str.indexOf('\n');
        spannable.setSpan(new AbsoluteSizeSpan(seekbarSmallFont), wrapIndex, spannable.length(), Spanned.SPAN_INCLUSIVE_EXCLUSIVE);
        textView.setText(spannable);
    }

}
